##
# Menu.py
# Description: Models a menu screen
##
import libtcodpy as libtcod
from Constants import *

class Menu:
    ##
    # init()
    #
    # Description: creates a console on which the menu is printed
    #
    # Parameters:
    #   header - The title of the menu (string)
    #   options - The contents of the menu. This cannot be longer than 26 (string[])
    #   width - The width of the menu (int)
    ##
    def __init__(self, header, options, width):
        #TODO: Handle more than 26 characters
        self.header = header
        self.options = options
        self.width = width

        if len(options) > 26:
            raise ValueError('The menu cannot have more than 26  options.')

        self.header_height = _getHeaderHeight(header, width)
        self.height = len(options) + self.header_height

        # Initialize the window to print the menu to
        self.window = libtcod.console_new(self.width, self.height)
        libtcod.console_set_default_foreground(self.window, libtcod.white)

        self.redrawMenu()

    ##
    # redrawMenu
    #
    # Description: redraws the menu with a new set of options
    #
    # Parameters:
    #   header - the new header, can be ignored to use previous header (string)
    #   options - the new options, can be ignored to use previous options (string[])
    #   width - the new width, can be ignored to use previous width (int)
    ##
    def redrawMenu(self, header=None, options=None, width=None):
        self.header = header or self.header
        self.options = options or self.options
        self.width = width or self.width
        if header is not None or width is not None:
            self.header_height = _getHeaderHeight(self.header, self.width)

        # Print the header
        libtcod.console_print_rect_ex(self.window, 0, 0, width, self.height, libtcod.BKGND_NONE, libtcod.LEFT, self.header)

        y = self.header_height
        letter_index = ord('a')
        for option_text in self.options:
            text = '(' + chr(letter_index) + ') ' + option_text
            libtcod.console_print_ex(self.window, 0, y, libtcod.BKGND_NONE, libtcod.LEFT, text)
            y += 1
            letter_index += 1

    ##
    # getMenuItem()
    #
    # Description: returns the menu item of the given character
    #
    # Parameters:
    #   char - the character index of a menu item (int)
    #
    # Returns: The element in options which corresponds the the character.
    ##
    def getMenuItem(self, char):
        if self.options:
            # Make sure the given char is correct
            if char < ord('a') or char >= ord('a') + len(self.options):
                return None
            # Make sure there is something in options
            return self.options[char - ord('a')]
        return None

    ##
    # applyTo()
    #
    # Description: Blits and draws the window to the given screen.
    #
    # Parameters:
    #   console - a console on which the menu will be drawn (Console -- made from libtcod.newConsole(w, h))
    #   foregroundAlpha - the opacity of the text. This must be in the range [0..1] (float)
    #   backgroundAlpha - the opacity of the background. This must be in the range [0..1] (float)
    ##
    def applyTo(self, console, foregroundAlpha=1.0, backgroundAlpha=1.0):
        if console is None:
            console = DEFAULT_CONSOLE

        # Center it on the screen
        x = SCREEN_WIDTH /2 - self.width/2
        y = SCREEN_HEIGHT/2 - self.height/2

        # applyTo the contents of the menu to the root console
        libtcod.console_blit(self.window, 0, 0, self.width, self.height, console, x, y, foregroundAlpha, backgroundAlpha)
        # Apply the changes
        libtcod.console_flush()

    ##
    # handleKeyPress()
    #
    # Description: Waits for a key to be pressed then handles it.
    #
    # Parameters:
    #   key: the keypress of the user (Key)
    #
    # Returns: the User's selection
    ##
    def handleKeyPress(self, key):
        if key:
            return self.getMenuItem(key.c)
        else:
            return libtcod.console_wait_for_keypress(True)

    ##
    # displayMenu()
    #
    # Description: activates the menu. This should only be used for the starting menus.
    # Note, the
    #
    # Returns: the user's selection (string)
    ##
    def displayMenu(self):
        # Clear the screen of everything
        libtcod.console_clear(DEFAULT_CONSOLE)

        # Add a background image
        im = libtcod.image_load("images/EDStart.png")

        # Display the background image
        libtcod.image_blit_2x(im, DEFAULT_CONSOLE, 0, 0)

        # Draw the menu on the specified console
        self.applyTo(DEFAULT_CONSOLE, backgroundAlpha=0)

        # Wait for input from the user
        keyPress = libtcod.console_wait_for_keypress(True)

        # Display the background image
        libtcod.image_blit_2x(im, DEFAULT_CONSOLE, 0, 0)
        libtcod.console_flush()

        selection = self.handleKeyPress(keyPress)

        # return the user's selection
        return selection

##
# _getHeaderHeight()
#
# Description: gets the number of lines the header will require
#
# Parameters:
#   header - the header text (int)
#   width - the width of the menu (int)
#
# Returns the height of the header
##
def _getHeaderHeight(header, width):
    from math import ceil
    return int(ceil(len(header) / float(width)))